package com.sinosoft.hydra.um.services;

import cn.com.sinux.spring.exception.ServiceException;
import cn.com.sinux.spring.utils.QueryHelper;
import cn.com.sinux.spring.utils.SpecificationHelper;
import cn.com.sinux.spring.utils.ValidatorUtils;
import com.sinosoft.hydra.timing.QuartzTaskScheduler;
import com.sinosoft.hydra.um.condition.SearchRoleCondition;
import com.sinosoft.hydra.um.constant.BaseConstant;
import com.sinosoft.hydra.um.dao.SysResourceDao;
import com.sinosoft.hydra.um.dao.SysRoleDao;
import com.sinosoft.hydra.um.domain.permission.SysRole;
import com.sinosoft.hydra.um.domain.permission.SysUserMember;
import com.sinosoft.hydra.um.repositories.SysRoleRepository;
import com.sinosoft.hydra.um.repositories.SysUserRepository;
import com.sinosoft.hydra.um.utils.AppUtils;
import com.sinosoft.hydra.um.vo.Node;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

;

/**
 * 角色业务层实现类，完成角色分配，新增修改查询操作
 * @time 2015-2-1
 * @desc 一些供角色调用的接口
 * @author Zhengt@sinux.com.cn
 */
@Service
public class SysRoleService{

    /**
     * 角色数据层
     */
    @Autowired
    private SysRoleRepository sysRoleRepository;
    /**
     * 角色dao数据层
     */
    @Autowired
    private SysRoleDao sysRoleDao;
    /**
     * 资源dao的数据层
     */
    @Autowired
    private SysResourceDao sysResourceDao;
    /**
     * 定时器任务调度
     */
    @Autowired
    private QuartzTaskScheduler quartzTaskScheduler;

    @Autowired
    private SysUserRepository userRepository;

    /**
     * 查询所有角色
     *
     * @param name 角色名
     * @return List<SysRole>  返回查询角色结果
     */

    public List<SysRole> findAll(String name) {
        SearchRoleCondition searchRoleCondition = new SearchRoleCondition();
        searchRoleCondition.setRoleName(name);
        searchRoleCondition.setLikeWord(true);
        searchRoleCondition.setAvailable(BaseConstant.INTEGER_TRUE);
        return findAllByPage(searchRoleCondition, null).getContent();
    }

    /**
     * 分页查询所有角色
     *
     * @param page 分页对象Pageable
     * @param role 提供根据角色名 和 是否是临时角色查询
     * @return Page<SysRole> 返回查询角色结果
     */

    public Page<SysRole> findAllByPage(SearchRoleCondition role, Pageable page) {
        return sysRoleRepository.findAll(buildSpecification(role), page);
    }

    /**
     * 传入角色id查询单个角色
     *
     * @param id 角色id
     */

    public SysRole findOne(String id) {
        return sysRoleRepository.findOne(id);
    }


    private Specification<SysRole> buildSpecification(SearchRoleCondition searchRoleCondition) {
        final SearchRoleCondition condition = searchRoleCondition == null
                ? new SearchRoleCondition()
                : searchRoleCondition;
        return SpecificationHelper.buildSpecification(new SpecificationHelper.SpecificationBuilder<SysRole>() {
        
            public void fillParam(Root<SysRole> root, CriteriaBuilder cb, List<Predicate> list) {
                if (StringUtils.isNotBlank(condition.getRoleName())) {
                    list.add(condition.isLikeWord()
                            ? cb.like(root.get("roleName").as(String.class), "%" + condition.getRoleName() + "%")
                            : cb.equal(root.get("roleName").as(String.class), condition.getRoleName()));
                }
                if (condition.getAvailable() != null) {
                    list.add(cb.equal(root.get("available").as(Integer.class), condition.getAvailable()));
                }
            }
        });
    }

    @Transactional
    public SysRole addRole(SysRole role) {
        if (StringUtils.isBlank(role.getRoleName())) {
            throw new ServiceException("角色名不能为空");
        }
        role.setCreateDate(new Date());
        role.setAvailable(BaseConstant.INTEGER_TRUE);
        if(role.getOrderNo() == null){
            role.setOrderNo(0);
        }
        return sysRoleRepository.save(role);
    }

    @Transactional
    public SysRole updateRole(SysRole role) {
        SysRole db = sysRoleRepository.findOne(role.getId());
        if (db == null) {
            throw new ServiceException("修改的资源不存在");
        }
        if (StringUtils.isBlank(role.getRoleName())) {
            throw new ServiceException("角色名不能为空");
        }
        db.setRoleName(role.getRoleName());
        db.setRoleDesc(role.getRoleDesc());
        db.setOrderNo(role.getOrderNo());
        if(db.getOrderNo() == null){
            db.setOrderNo(0);
        }
        sysRoleRepository.save(db);
        AppUtils.clearAllCachedAuthorizationInfo();
        return db;
    }

    @Transactional
    public SysRole saveRoleResources(String id, List<String> resourceIds) {
        SysRole db = sysRoleRepository.findOne(id);
        if (db == null) {
            throw new ServiceException("修改的资源不存在");
        }
        sysResourceDao.saveRoleResource(resourceIds, id);
        AppUtils.clearAllCachedAuthorizationInfo();
        return sysRoleRepository.findOne(id);
    }

    @Transactional
    public SysRole saveRoleUsers(String id, List<String> userIds) {
        SysRole db = sysRoleRepository.findOne(id);
        if (db == null) {
            throw new ServiceException("修改的资源不存在");
        }
        List<SysUserMember> userMembers = userRepository.findAll(userIds);
        db.setSysUserMembers(userMembers);
        sysRoleRepository.save(db);
        AppUtils.clearAllCachedAuthorizationInfo();
        return db;
    }

    @Transactional
    public SysRole removeRoleUsers(String id, final List<String> userIds) {
        SysRole db = sysRoleRepository.findOne(id);
        if (db == null) {
            throw new ServiceException("修改的资源不存在");
        }
        List<SysUserMember> members = db.getSysUserMembers();
        members = QueryHelper.doRemove(members, new QueryHelper.MatchWorker<SysUserMember>() {

            public boolean match(SysUserMember sysUserMember) {
                return userIds.contains(sysUserMember.getId());
            }
        });
        db.setSysUserMembers(members);
        sysRoleRepository.save(db);
        AppUtils.clearAllCachedAuthorizationInfo();
        return db;
    }


    public SysRole addRoleUsers(String id, List<String> userIds) {
        SysRole db = sysRoleRepository.findOne(id);
        if (db == null) {
            throw new ServiceException("修改的资源不存在");
        }
        List<SysUserMember> members = db.getSysUserMembers();
        List<SysUserMember> myM = userRepository.findAll(userIds);
        members.addAll(myM);
        db.setSysUserMembers(QueryHelper.doDistinctByProperty(members, true, new QueryHelper.PropertyReader<SysUserMember, String>() {
        
            public String read(SysUserMember sysUserMember) {
                return sysUserMember.getId();
            }
        }));
        sysRoleRepository.save(db);
        AppUtils.clearAllCachedAuthorizationInfo();
        return db;
    }

    /**
     * 删除角色
     *
     * @param ids 角色id字符串，格式为: JsonList(eg:{"ids":["1","2","3"]})
     * @return Map<String,Object>    键值为AppConfig的常量
     * @desc 会自动删除其与父角色以及子角色的关联关系
     */
    @Transactional
    public List<SysRole> deleteRole(List<String> ids) {
        if (ValidatorUtils.isArrayEmpty(ids)) {
            throw new ServiceException("参数不合法");
        }
        List<SysRole> roles = new LinkedList<SysRole>();
        try {
            for (String id : ids) {
                SysRole role = sysRoleRepository.findOne(id);
                String jobId = role.getJobId();
                sysRoleRepository.delete(role);
                if (StringUtils.isNotBlank(jobId)) {
                    quartzTaskScheduler.terminateJob(jobId);
                }
                roles.add(role);
            }
            AppUtils.clearAllCachedAuthorizationInfo();
        } catch (Exception e) {
            throw new ServiceException("系统错误");
        }
        return roles;
    }

    /**
     * 储存用户角色
     *
     * @param sysRoles 角色id字符串，格式为: JsonList(eg:{"ids":["1","2","3"]})
     * @param userId   用户id
     */
    @Transactional
    public List<SysRole> saveUserRole(List<String> sysRoles, String userId) {
        sysRoleDao.saveUserRole(sysRoles, userId);
        return sysRoleRepository.findAll(sysRoles);
    }

    /**
     * 为指定注册模块选择角色的树(可多选)
     *
     * @param moduleRegId 部门ID
     * @return 角色树
     */

    public List<Node> roleListForModuleRegister(String moduleRegId) {
        List<Node> nodeLi = new ArrayList<Node>();
        List<SysRole> roleLi = this.findAll("");

        List<String> stringLi = new ArrayList<String>();
        List<String> existsIds = new ArrayList<String>();
        if (stringLi != null && stringLi.size() > 0) {
            for (String string : stringLi) {
                if (StringUtils.isNotBlank(string))
                    existsIds = Arrays.asList(string.split(","));
            }
        }
        for (SysRole r : roleLi) {
            Node node = new Node();
            node.setId(r.getId());
            node.setName(r.getRoleName());
            if (existsIds.contains(r.getId())) {
                node.setChecked(true);
            }
            nodeLi.add(node);
        }
        return nodeLi;
    }

    /**
     * 调度器中的删除单个角色
     *
     * @param id 角色id
     */

    public void deleteARole(String id) {
        SysRole role = sysRoleRepository.findOne(id);
        sysRoleRepository.delete(role);
    }
}
